package com.hwsc.pay.controller;




import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.csii.test.sm.Sm4Util;
import com.hwsc.pay.annotation.IgnoreResponseAdvice;
import com.hwsc.pay.service.impl.RedisLockService;
import com.hwsc.pay.utils.VerifySignUtils;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.config.RabbitMqConfig;
import com.hwsc.pay.constant.Constants;
import com.ruoyi.common.constant.RedisConstants;
import com.hwsc.pay.service.IPayService;
import com.ruoyi.common.entity.PaymentCallbackMessage;
import com.ruoyi.common.entity.Result;
import com.hwsc.pay.voice.SpeechSynthesizerDemo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Api(tags = "PayController", description = "支付接口")
@RestController
@RequestMapping("/pay")
@CrossOrigin
public class PayController {
    private static final Logger log = LoggerFactory.getLogger(PayController.class);
    @Autowired
    private IPayService payService;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private RedisLockService redisLockService;

    @PostConstruct
    public void init() {
        // 设置消息确认回调
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                log.info("消息发送成功，correlationData: {}", correlationData);
            } else {
                log.error("消息发送失败，correlationData: {}, cause: {}", correlationData, cause);
            }
        });

        // 设置消息返回回调
        rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
            log.error("消息发送失败，消息被退回，exchange: {}, routingKey: {}, replyCode: {}, replyText: {}", 
                exchange, routingKey, replyCode, replyText);
        });
    }



    @ApiOperation(value = "获取银行支付页面")
    @GetMapping("/trans")
    @RepeatSubmit(interval = 3000, message = "请求过于频繁")
    public Result trans(@ApiParam(value = "商户号，用于标识商户身份", required = true)
                               @RequestParam String merchantNo,
                               @ApiParam(value = "支付金额，单位为元", required = true)
                               @RequestParam BigDecimal amount,
                               @ApiParam(value = "签名，用于验证请求的合法性", required = true, example = "abc123def456")
                               @RequestParam String sign,
                        HttpServletRequest request){
        try {
//            //验签
//            VerifySignUtils.verifySign(merchantNo, sign);
            log.info("调起银行支付页面, 支付商户号={},金额={},签名={}", merchantNo, amount, sign);
            if (amount == null) {
                throw new Exception("金额不为空");
            }
            //银行支付接口单位为分
            int merchantAmountInt = amount.multiply(new BigDecimal(100)).intValue();
            if (merchantAmountInt <= 0) {
                throw new Exception("金额不合法");
            }
            String token=request.getHeader("Authori-zation");
            return Result.success(payService.getPayUrl(token,merchantNo, String.valueOf(merchantAmountInt)));
        }catch (Exception e)
        {
            e.printStackTrace();
        }
        return Result.error("商户不存在");
    }

    //支付回调
    @ApiIgnore
    @RequestMapping("/callback")
    @IgnoreResponseAdvice
    public String callback(HttpServletRequest request) {
        //获取订单数据
        PaymentCallbackMessage callbackMessage = getPaymentCallbackMessage(request);
        String orderId = callbackMessage.getOrderId();
        String lockKey = RedisConstants.PAYMENT_DUPLICATE_LOCK_ + orderId;
        // 设置分布式锁 去掉重复订单
        if (!redisLockService.tryLock(lockKey, 30, TimeUnit.MINUTES)) {
            log.info("重复请求，订单号={}", orderId);
            return "";
        }
        //查询数据库订单是否已经处理 防止redis挂掉
        try {
            // 播报语音支付消息（确保只执行一次）
            String speechKey = "PAYMENT_SPEECH_PREFIX" + orderId;
            log.info("尝试设置语音播报key: {}, orderId: {}", speechKey, orderId);
            // 设置24小时过期时间
            Boolean isFirstCall = redisTemplate.opsForValue().setIfAbsent(speechKey, "1", 24, TimeUnit.MINUTES);
            log.info("语音播报key设置结果: {}, orderId: {}", isFirstCall, orderId);
            if (Boolean.TRUE.equals(isFirstCall)) {
                // 只有第一次设置成功时才执行语音播报
                log.info("开始执行语音播报, amount: {}, orderId: {}", callbackMessage.getTransAmount(), callbackMessage.getOrderId());
                SpeechSynthesizerDemo.synthesis(String.valueOf(callbackMessage.getTransAmount()), callbackMessage.getOrderId());
                // 发送WebSocket通知消息到RabbitMQ
                JSONObject notifyMessage = new JSONObject();
                notifyMessage.put("type", "payment");
                notifyMessage.put("orderId", callbackMessage.getOrderId());
                notifyMessage.put("merchantId", callbackMessage.getMerchantId());
                notifyMessage.put("amount", callbackMessage.getTransAmount());
                callbackMessage.setMessageInfo(notifyMessage.toJSONString());
                log.info("已发送WebSocket通知消息到RabbitMQ, orderId={}", orderId);
                // 处理支付回调逻辑
                //unipush2通知
                rabbitTemplate.convertAndSend(RabbitMqConfig.EXCHANGE_NAME, RabbitMqConfig.ROUTING_KEY, callbackMessage);
            }


        } finally {
            // 释放锁
            redisLockService.releaseLock(lockKey);
        }
        return "success";
    }

    private static PaymentCallbackMessage getPaymentCallbackMessage(HttpServletRequest request) {
        String jsonStr = JSONUtil.toJsonStr(request.getParameterMap());
        log.info("支付回调=={}", jsonStr);
        String encryptText = getEncryptText(jsonStr);
        String orderInfoJsonStr = null;
        try {
            orderInfoJsonStr = Sm4Util.decryptEcb(Constants.DECRYPT_ECB_KEY_TEST, encryptText);
            log.info("支付回调解密后=={}", orderInfoJsonStr);
        } catch (Exception e) {
            log.error("支付回调解密失败", e);
            throw new RuntimeException(e);
        }

        PaymentCallbackMessage callbackMessage = JSON.parseObject(orderInfoJsonStr, PaymentCallbackMessage.class);
        return callbackMessage;
    }

    //获取密文
    public static String getEncryptText(String jsonStr) {
        JSONObject jsonObject = JSON.parseObject(jsonStr);
        JSONArray orderInfo = JSON.parseArray(String.valueOf(jsonObject.get("orderInfo")));
        return String.valueOf(orderInfo.get(0));
    }
}
